<template>
  <div class="svg-container">
    <div class="beds-example-container">
      <p>房间布局</p>
      <p v-if="!readOnly">请拖动空床模块至房间布局图中，完成后点击保存</p>
      <div class="beds-example">
        <span v-if="!readOnly"
          class="bed" draggable="true"
          style="background-color: #15c098;"
          @dragstart="dragstart"
          @dragend="dragend">
          空床
        </span>
        <span v-else
              class="bed" draggable="false"
              style="background-color: #15c098;">
          空床
        </span>
      </div>
    </div>
    <div class="" style="width: 85%; height: 87%;">
      <template v-if="!readOnly">
        <p>双击房间进行编辑、点击房间右上角删除</p>
        <span>
          <el-button @click="reset">重置布局</el-button>
        </span>
      </template>
      <div id="test1" class="svg-border" :style="'width:' + SVG_SIZE.WIDTH + 'px;height:' + SVG_SIZE.HEIGHT + 'px;'">
        <svg v-if="!readOnly" width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"
             @contextmenu.prevent
             @mouseup.stop="mouseup"
             @mousemove="mousemove"
             @mousedown="clearActivatedBed"
             @mouseout="mouseout"
             @dragover="dragover"
             @drop.prevent="drop">
          <a v-for="(bed,index) in beds"
             v-if="beds"
             @contextmenu="openMenu(index, $event)"
             @mousedown.stop="moveStart(index, $event)">
            <rect class="svg-movable"
                  :class="{ 'activated-bed' : bed === activatedBed}"
                  :style="'fill: #ffffff;' + 'stroke:black; fill-opacity:1; stroke-width:' + ROOM_SIZE.STROKE_WIDTH + ';'"
                  :x="bed.x * SVG_SIZE.WIDTH"
                  :y="bed.y * SVG_SIZE.HEIGHT"
                  :width="bed.width * SVG_SIZE.WIDTH"
                  :height="bed.height * SVG_SIZE.HEIGHT"/>
          </a>
          <rect class="svg-resizable" style="fill:white; stroke:black; fill-opacity:0; stroke-width:1;" width="5" height="5"
                v-if="activatedBed"
                @mousedown.stop="resizeStart"
                :x="resizer.x * SVG_SIZE.WIDTH"
                :y="resizer.y * SVG_SIZE.HEIGHT"/>
          <text class="svg-clickable" fill="black"
                v-if="activatedBed"
                :x="closer.x * SVG_SIZE.WIDTH - 12"
                :y="closer.y * SVG_SIZE.HEIGHT + 12"
                @mousedown.stop
                @click.stop="removeBed">x</text>
        </svg>
        <svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" v-else>
          <a v-for="(bed,index) in beds"
             v-if="beds">
            <rect
                  :style="'fill: #ffffff;' + 'stroke:black; fill-opacity:1; stroke-width:' + ROOM_SIZE.STROKE_WIDTH + ';'"
                  :x="bed.x * SVG_SIZE.WIDTH"
                  :y="bed.y * SVG_SIZE.HEIGHT"
                  :width="bed.width * SVG_SIZE.WIDTH"
                  :height="bed.height * SVG_SIZE.HEIGHT"/>
          </a>
        </svg>
      </div>
      <el-card v-if="menu && !readOnly" class="bed-menu"
               :style="menuStyle"
               @click.stop>
        <div class="text item"><el-button @click="removeBed">删除床位</el-button></div>
      </el-card>
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
  const MODE = {
    NONE: 0,
    MOVE: 1,
    RESIZE: 2
  };
  const SVG_SIZE = {
    WIDTH: 1000,
    HEIGHT: 600,
  };
  const ROOM_SIZE = {
    STROKE_WIDTH: 1,
  }
  const defaultGeo = {
    x: 0.001,
    y: 0.001,
    width: 0.15,
    height: 0.1,
  }

  export default {
    props: ["bedsJson", "readOnly"],
    watch: {
      bedsJson() {
        this.init();
      },
      bedCount(count) {
        this.$emit("bedCountChange", count);
      },
    },
    data() {
      return {
        SVG_SIZE,
        ROOM_SIZE,
        dragObj: "",  // 正在拖动的房间样本
        bedsExample: [],  // 房间样本
        beds: [],  // 房间布局数据
        activatedBed: null,  // 当前激活房间
        mode: MODE.NONE,  // 当前激活房间正在进行的操作：无/移动/缩放,
        menu: null,
      }
    },
    computed: {
      bedCount() {
        let count = 0;
        if(this.beds.length) {
          count = this.beds.length;
        }
        return count;
      },
      resizer() {
        return {
          x: this.activatedBed.x + this.activatedBed.width,
          y: this.activatedBed.y + this.activatedBed.height,
        }
      },
      closer() {
        return {
          x: this.activatedBed.x + this.activatedBed.width - 12,
          y: this.activatedBed.y + 12,
        }
      },
      menuStyle() {
        let style = null;
        if(this.menu) {
          style = {
            border: '1px',
            solid: '#f00',
            position: 'absolute',
            left: this.menu.x  * SVG_SIZE.WIDTH - 290 + 'px',
            top: this.menu.y  * SVG_SIZE.HEIGHT - 135 + 'px',
          }
        }
        return style;
      }
    },
    methods: {
      init() {
        this.clearActivatedBed();
        if(this.bedsJson) {
          this.beds = JSON.parse(this.bedsJson);
        } else {
          this.beds =[];
        }
      },
      // 判断图形是否超出svg区域
      outOfArea(geo) {
        let flag = false;
        if(geo) {
          let x = geo.x;
          let y = geo.y;
          let width = geo.width;
          let height = geo.height;
          let areaWidth = SVG_SIZE.WIDTH;
          let areaHeight = SVG_SIZE.HEIGHT;
          if(x <= 0 ||
            x >= areaWidth - width ||
            y <= 0 ||
            y >= areaHeight - height) {
            flag = true;
          }
        }
        return flag;
      },
      moveStart(index, event) {
        let buttonCode = event.button;
        const CODE_LEFT_MOUTH = 0;
        if(buttonCode === CODE_LEFT_MOUTH) {
          this.activatedBed = this.beds[index];
          this.mode = MODE.MOVE;
          this.menu = null;
        }
      },
      mouseup() {
        this.mode = MODE.NONE;
      },
      // 鼠标移出svg区域时终止操作
      mouseout(e) {
        let toEle = e.toElement;  // 鼠标移入的元素
        let svg = document.getElementsByTagName('svg')[0];
        let svgChildren = svg.getElementsByTagName('*');  // svg所有后代
        for(var i=0; i<svgChildren.length; i++) {
          if(svg === toEle || svgChildren[i] === toEle) {
            return ;  // 如果移入元素为svg后代或本身则不终止操作
          }
        }
        // 鼠标移出svg以外区域
        this.mode = MODE.NONE;
      },
      moving(e) {
        // 假设移动后没有出界则继续操作，否则禁止操作
        let mockObj = Object.assign({}, this.activatedBed);
        let x = e.movementX  / SVG_SIZE.WIDTH;
        let y = e.movementY  / SVG_SIZE.HEIGHT;
        mockObj.x += x;
        mockObj.y += y;
        if(this.activatedBed && !this.outOfArea(mockObj)) {
          this.activatedBed.x += x;
          this.activatedBed.y += y;
        }
      },
      resizeStart(event) {
        let buttonCode = event.button;
        const CODE_LEFT_MOUTH = 0;
        if(buttonCode === CODE_LEFT_MOUTH) {
          this.mode = MODE.RESIZE;
        }
      },
      resizing(e) {
        const minWidth = 0.025;
        const minHeight = 0.04;
        // 假设缩放后大小合理则继续操作，否则禁止操作
        let mockObj = Object.assign({}, this.activatedBed);
        let x = e.movementX  / SVG_SIZE.WIDTH;
        let y = e.movementY  / SVG_SIZE.HEIGHT;
        mockObj.width += x;
        mockObj.height += y;
        if(mockObj.width >= minWidth && mockObj.height >= minHeight && !this.outOfArea(mockObj)) {
          this.activatedBed.width += x;
          this.activatedBed.height += y;
        }
      },
      mousemove(e) {
        if(this.mode === MODE.MOVE) {
          this.moving(e);
        } else if(this.mode === MODE.RESIZE) {
          this.resizing(e);
        }
      },
      clearActivatedBed() {
        this.activatedBed = null;
        this.clearMenu();
        this.mode = MODE.NONE;
      },
      openMenu(index, e) {
        this.activatedBed = this.beds[index];
        this.mode = MODE.NONE;
        this.menu = {
          x: e.clientX / SVG_SIZE.WIDTH,
          y: e.clientY  / SVG_SIZE.HEIGHT,
        }
      },
      clearMenu() {
        this.menu = null;
      },
      dragstart() {
        this.dragObj = true;
      },
      dragend() {
        this.dragObj = false;
      },
      drop() {
        if(this.dragObj) {
          this.addBed();
        }
      },
      dragover(e) {
        // 只允许拖动指定元素进入svg容器
        if(this.dragObj) {
          e.preventDefault();
        }
      },
      addBed() {
        let handlePosition = (addBed) => {
          for(let bed of this.beds) {
            if(bed.x === addBed.x && bed.y === addBed.y) {
              addBed.x += 0.01;
              addBed.y += 0.01;
              handlePosition(addBed);
              break;
            }
          }
          return addBed;
        }
        this.beds.push(handlePosition(JSON.parse(JSON.stringify(defaultGeo))));
      },
      removeBed() {
        this.clearMenu();
        let removeLocalData = () => {
          // 删除房间数据
          let removeIndex = this.beds.findIndex((bed) => {
            return bed === this.activatedBed;
          });
          this.beds.splice(removeIndex,1);
          // 删除成功后清除当前激活元素
          this.clearActivatedBed();
        }
        removeLocalData();
      },
      reset() {
        this.init();
      },
    },
    mounted() {
      this.init();
    }
  }
</script>

<style>
  .svg-container {
    width:100%;
  }
  .svg-movable {
    cursor: move
  }
  .svg-resizable {
    cursor: nw-resize
  }
  .svg-clickable {
    cursor: pointer
  }
  svg text {
    -moz-user-select:none;/*火狐*/
    -webkit-user-select:none;/*webkit浏览器*/
    -ms-user-select:none;/*IE10*/
    -khtml-user-select:none;/*早期浏览器*/
    user-select:none;
  }
  .svg-border {
    border:2px solid #D5D5D5;
    background: url("../../img/shading.png");
  }
  .beds-example-container {
    margin-bottom: 50px;
  }
  .beds-example-container .beds-example {
    margin-top: 20px;
  }
  .beds-example-container .bed {
    cursor: default;
    border-style:solid;
    border-color:grey;
    margin-right: 30px;
  }
  .beds-example-container .bed * {
    cursor: default;
    border-style:solid;
    border-color:black;
  }

  .bed-menu {
  }

  .bed-menu text {
    font-size: 14px;
  }

  .bed-menu .item {
    margin-top: 10px;
  }
</style>
